package org.chainsale.prefuse.graph;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

import org.chainsale.bean.ActiveItem;
import org.chainsale.bean.Practitioner;
import org.chainsale.common.PractitionerFactory;
import org.chainsale.common.Utils;
import org.chainsale.main.Data;
import org.chainsale.prefuse.view.TreeView;

import prefuse.Visualization;
import prefuse.controls.ControlAdapter;
import prefuse.data.Node;
import prefuse.data.Table;
import prefuse.data.Tree;
import prefuse.util.ui.JFastLabel;
import prefuse.util.ui.JSearchPanel;
import prefuse.visual.VisualItem;

public class FuseTreePanel extends JPanel {

	private static final long serialVersionUID = 1L;
	
	private static final Color BACKGROUND = Color.WHITE;
	private static final Color FOREGROUND = Color.BLACK;
	private static final String GROUP_TREE_NODES = "tree.nodes";
	private static final String LABEL = "description";
	
	private TreeView tview = null;
	private Table m_nodes = null;
	private Tree m_tree = null;
	private Map<Integer, Node> nodeMap = new HashMap<Integer, Node>();
	private Map<Integer, Practitioner> pracMap = new HashMap<Integer, Practitioner>();
	
	public FuseTreePanel() {
		
		
		try {
			m_tree = new Tree();
			m_nodes = m_tree.getNodeTable();
			
			// add declarations
			Utils.addColumns(m_nodes);

			// add nodes
			Practitioner root = Data.createData4Tree();
			createNode4Tree(root);
			ActiveItem.getInstance().setActivePrac(root);
			
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}

		// create a new tree map
		tview = new TreeView(m_tree, LABEL);
		tview.setBackground(BACKGROUND);
		tview.setForeground(FOREGROUND);
		
		// create a search panel for the tree map
		JSearchPanel search = new JSearchPanel(tview.getVisualization(), GROUP_TREE_NODES, Visualization.SEARCH_ITEMS, LABEL, true, true);
		search.setShowResultCount(true);
		search.setBorder(BorderFactory.createEmptyBorder(5, 5, 4, 0));
		search.setFont(Utils.YA_HEI_FONT);
		search.setBackground(BACKGROUND);
		search.setForeground(FOREGROUND);

		final JFastLabel title = new JFastLabel(" ");
		title.setFont(Utils.YA_HEI_FONT);
		title.setPreferredSize(new Dimension(350, 20));
		title.setVerticalAlignment(SwingConstants.BOTTOM);
		title.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0));
		title.setBackground(BACKGROUND);
		title.setForeground(FOREGROUND);

		tview.addControlListener(new ControlAdapter() {
			public void itemEntered(VisualItem item, MouseEvent e) {
				if (item.canGetInt("id")) {
					try {
						int activeId = item.getInt("id");
						Practitioner p = pracMap.get(activeId);
						StringBuilder desc = new StringBuilder(p.getName()).append("  ")
												.append(p.getRank().getName()).append("  ")
												.append(p.getShare());
						title.setText(desc.toString());
					} catch (Exception ex) {
						ex.printStackTrace();
					}
				}
			}
			
			public void itemClicked(VisualItem item, MouseEvent e) {
				int activeId = item.getInt("id");
				
				ActiveItem.getInstance().setActiveId(item.getInt("id"));
				ActiveItem.getInstance().setActivePrac(pracMap.get(activeId));
				
				ActiveItem.getInstance().changeNodeProperties();
			}

			public void itemExited(VisualItem item, MouseEvent e) {
				title.setText(null);
			}
		});

		Box box = new Box(BoxLayout.X_AXIS);
		box.add(Box.createHorizontalStrut(10));
		box.add(title);
		box.add(Box.createHorizontalGlue());
		box.add(search);
		box.add(Box.createHorizontalStrut(3));
		box.setBackground(BACKGROUND);

		setLayout(new BorderLayout());
		setBackground(BACKGROUND);
		setForeground(FOREGROUND);
		add(tview, BorderLayout.CENTER);
		add(box, BorderLayout.SOUTH);

	}
	
	public void createNode4Tree(Practitioner p1) {
		Node n = null;
		if (p1.getSuperior() == null) {
			n = m_tree.addRoot();
		} else {
			n = m_tree.addChild(nodeMap.get(p1.getSuperior().getId()));
		}

		Utils.copyProperties(p1, n);

		nodeMap.put(p1.getId(), n);
		pracMap.put(p1.getId(), p1);

		List<Practitioner> pps = new ArrayList<Practitioner>(p1.getUnderlings());
		while (!pps.isEmpty()) {
			for (int i = 0; i < pps.size();) {
				p1 = pps.get(i);
				createNode4Tree(p1);

				pps.remove(i);
			}
		}

	}

	public Practitioner addOneNode(Practitioner superior, int addedNum, String addedName) {
		Practitioner p1 = null;
		
		if (addedNum == 1 && Utils.isNotEmpty(addedName)) {
			p1 = PractitionerFactory.create(addedName);
		} else {
			p1 = PractitionerFactory.create();
		}
		
		superior.addUnderling(p1);
		
		Node n = m_tree.addChild(nodeMap.get(superior.getId()));

		resetNodeDesc(superior);
		
		Utils.copyProperties(p1, n);

		nodeMap.put(p1.getId(), n);
		pracMap.put(p1.getId(), p1);
		
		return p1;
	}
	
	public Practitioner getPractitioner(Integer id) {
		return pracMap.get(id);
	}
	
	public synchronized void repaint() {
//		System.out.println("repaint " + i++);
		try {
			
			tview.getVisualization().cancel("animatePaint");
			tview.getVisualization().run("fullPaint");
			tview.getVisualization().run("animatePaint");
			
			tview.getVisualization().run("filter");
			
			tview.getVisualization().runAfter("fullPaint", "treeLayout");
		} catch (Throwable e) {
//			System.out.println("Throwable " + j++ + "  -- " + e.getMessage());
//			e.printStackTrace();
		}
	}
	
	private void resetNodeDesc(Practitioner p) {
		nodeMap.get(p.getId()).set(LABEL, p.getDescription());
		while (Utils.isChainNotEnded(p)) {
			p = p.getSuperior();
			resetNodeDesc(p);
		}
	}

}
